package concurrency

// WebsiteChecker checks a url, returning a bool.
type WebsiteChecker func(string) bool

// 因为我们不需要任何一个要命名的值，
// 它们中的每一个在结构中都是匿名的；这在很难知道用什么命名值的时候可能很有用。
type result struct {
	string
	bool
}

// CheckWebsites takes a WebsiteChecker and a slice of urls and returns  a map.
// of urls to the result of checking each url with the WebsiteChecker function.
func CheckWebsites(wc WebsiteChecker, urls []string) map[string]bool {
	results := make(map[string]bool)
	resultChannel := make(chan result)

	for _, url := range urls {
		// 通过给每个匿名函数一个参数 url(u)，然后用 url 作为参数调用匿名函数，
		// 我们确保 u 的值固定为循环迭代的 url 值，重新启动 goroutine。u 是 url 值的副本，因此无法更改
		go func(u string) {
			// go test -race 可查出一些 data race
			// 当我们迭代 urls 时，不是直接写入 map，
			// 而是使用 send statement 将每个调用 wc 的 result 结构体发送到 resultChannel
			resultChannel <- result{u, wc(u)}
		}(url)
	}

	for i := 0; i < len(urls); i++ {
		// receive expression
		result := <-resultChannel
		results[result.string] = result.bool
	}

	return results
}
